* - a(s(taya{sv})) - Map of ref name -> (latest commit size, latest commit checksum, additional metadata), sorted by ref name
* - a{sv} - Additional metadata, at the current time the following are defined:
* - key: "ostree.static-deltas", value: a{sv}, static delta name -> 32 bytes of checksum
+ * - key: "ostree.summary.last-modified", value: t, timestamp (seconds since
+ * the Unix epoch in UTC, big-endian) when the summary was last regenerated
+ * (similar to the HTTP `Last-Modified` header)
+ * - key: "ostree.summary.expires", value: t, timestamp (seconds since the
+ * Unix epoch in UTC, big-endian) after which the summary is considered
+ * stale and should be re-downloaded if possible (similar to the HTTP
+ * `Expires` header)
+ *
+ * The currently defined keys for the `a{sv}` of additional metadata for each commit are:
+ * - key: `ostree.commit.timestamp`, value: `t`, timestamp (seconds since the
+ * Unix epoch in UTC, big-endian) when the commit was committed
*/
#define OSTREE_SUMMARY_GVARIANT_STRING "(a(s(taya{sv}))a{sv})"
#define OSTREE_SUMMARY_GVARIANT_FORMAT G_VARIANT_TYPE (OSTREE_SUMMARY_GVARIANT_STRING)
* */
#define _OSTREE_MAX_OUTSTANDING_WRITE_REQUESTS 16
+/* Well-known keys for the additional metadata field in a summary file. */
+#define OSTREE_SUMMARY_LAST_MODIFIED "ostree.summary.last-modified"
+#define OSTREE_SUMMARY_EXPIRES "ostree.summary.expires"
+
+/* Well-known keys for the additional metadata field in a commit in a ref entry
+ * in a summary file. */
+#define OSTREE_COMMIT_TIMESTAMP "ostree.commit.timestamp"
+
typedef enum {
OSTREE_REPO_TEST_ERROR_PRE_COMMIT = (1 << 0)
} OstreeRepoTestErrorFlags;
* An OSTree repository can contain a high level "summary" file that
* describes the available branches and other metadata.
*
+ * If the timetable for making commits and updating the summary file is fairly
+ * regular, setting the `ostree.summary.expires` key in @additional_metadata
+ * will aid clients in working out when to check for updates.
+ *
* It is regenerated automatically after a commit if
* `core/commit-update-summary` is set.
*/
const char *commit = g_hash_table_lookup (refs, ref);
g_autofree char *remotename = NULL;
g_autoptr(GVariant) commit_obj = NULL;
+ g_auto(GVariantDict) commit_metadata_builder = OT_VARIANT_BUILDER_INITIALIZER;
+ guint64 commit_timestamp;
+ g_autoptr(GDateTime) dt = NULL;
g_assert (commit);
if (!ostree_repo_load_variant (self, OSTREE_OBJECT_TYPE_COMMIT, commit, &commit_obj, error))
goto out;
- g_variant_builder_add_value (refs_builder,
+ g_variant_dict_init (&commit_metadata_builder, NULL);
+
+ /* Forward the commit’s timestamp if it’s valid. */
+ commit_timestamp = ostree_commit_get_timestamp (commit_obj);
+ dt = g_date_time_new_from_unix_utc (commit_timestamp);
+
+ if (dt != NULL)
+ g_variant_dict_insert_value (&commit_metadata_builder, OSTREE_COMMIT_TIMESTAMP,
+ g_variant_new_uint64 (GUINT64_TO_BE (commit_timestamp)));
+
+ g_variant_builder_add_value (refs_builder,
g_variant_new ("(s(t@ay@a{sv}))", ref,
(guint64) g_variant_get_size (commit_obj),
ostree_checksum_to_bytes_v (commit),
- ot_gvariant_new_empty_string_dict ()));
+ g_variant_dict_end (&commit_metadata_builder)));
}
g_variant_dict_insert_value (&additional_metadata_builder, OSTREE_SUMMARY_STATIC_DELTAS, g_variant_dict_end (&deltas_builder));
}
+ {
+ g_variant_dict_insert_value (&additional_metadata_builder, OSTREE_SUMMARY_LAST_MODIFIED,
+ g_variant_new_uint64 (GUINT64_TO_BE (g_get_real_time () / G_USEC_PER_SEC)));
+ }
+
{
g_autoptr(GVariantBuilder) summary_builder =
g_variant_builder_new (OSTREE_SUMMARY_GVARIANT_FORMAT);